package com.bestcem.xm.user.service.impl;

import cn.hutool.core.lang.ObjectId;
import com.alibaba.fastjson.JSON;
import com.bestcem.xm.componet.redis.service.RedisService;
import com.bestcem.xm.user.config.properties.SettingProperties;
import com.bestcem.xm.user.enums.MfaSettingAuthMethodEnum;
import com.bestcem.xm.user.enums.OrgWalletConfigRechargeLimitEnum;
import com.bestcem.xm.user.enums.OrganizationSourceEnum;
import com.bestcem.xm.user.enums.UserEnum;
import com.bestcem.xm.user.grpc.client.DeliverGrpcService;
import com.bestcem.xm.user.grpc.client.UserWalletGrpcService;
import com.bestcem.xm.user.mq.message.organization.OrgCreateMessage;
import com.bestcem.xm.user.service.OrganizationService;
import com.bestcem.xm.user.service.OrganizationWalletConfigService;
import com.bestcem.xm.user.service.UserMfaSettingService;
import com.bestcem.xm.user.service.UserMqConsumeService;
import com.bestcem.xm.user.service.dto.organization.OrganizationWalletConfigDTO;
import com.bestcem.xm.user.service.dto.user.OrganizationDTO;
import com.bestcem.xm.user.service.dto.user.UserMfaSettingDTO;
import com.bestcem.xm.user.util.business.UserCacheUtil;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 用户mq消费逻辑服务
 *
 * @author wangyunyun <yunyun.wang@idiaoyan.com>
 * @version v1.0
 * @date 2022/7/16 18:17
 */
@Slf4j
@Service
public class UserMqConsumeServiceImpl implements UserMqConsumeService {

    @Resource
    private UserMfaSettingService userMfaSettingService;

    @Resource
    private UserCacheUtil userCacheUtil;

    @Resource
    private OrganizationService organizationService;

    @Resource
    private UserWalletGrpcService userWalletGrpcService;

    @Resource
    private OrganizationWalletConfigService organizationWalletConfigService;

    @Resource
    private SettingProperties settingProperties;

    @Resource
    private RedisService redisService;

    @Resource
    private DeliverGrpcService deliverGrpcClientService;

    /**
     * 创建公司消息消费锁 user_org_create_listener_{org_id}
     */
    public static final String USER_ORG_CREATE_LISTENER_LOCK = "user_org_create_listener_{0}}";

    @Override
    public void createMfaSettingForOrg(OrgCreateMessage message) {
        // 查询是否已经有mfa setting
        UserMfaSettingDTO mfaSettingDTO = userMfaSettingService.getMfaSettingByOrgId(message.getOrgId()).getData();
        if (mfaSettingDTO != null) {
            return;
        }
        // 保存公司mfa setting
        UserMfaSettingDTO dto = new UserMfaSettingDTO();
        dto.setOrgId(message.getOrgId())
                .setOpenMfa(UserEnum.USER_NO.getFlag())
                .setAuthMethod(MfaSettingAuthMethodEnum.MFASETTING_AUTH_METHOD_SMS.getType());
        userMfaSettingService.insertSelective(dto);
    }

    @Override
    public void createCorporateWallet(OrgCreateMessage message) {
        // 查询公司
        OrganizationDTO org = organizationService.selectByPrimaryKey(message.getOrgId()).getData();
        if (org == null || StringUtils.isNotBlank(org.getCorpWallet())) {
            if (log.isInfoEnabled()) {
                log.info("[USER.ORG_CREATED] 机构不存在 orgId:{}", message.getOrgId());
            }
            return;
        }
        // 创建企业钱包
        String corpWallet = userWalletGrpcService.createPlatformWallet(settingProperties.getRedPaperPlatformCode(), org.getCode(), org);
        if (StringUtils.isNotBlank(corpWallet)) {
            // 更新公司的企业钱包id
            OrganizationDTO updateOrg = new OrganizationDTO();
            updateOrg.setOrgId(org.getOrgId());
            updateOrg.setCorpWallet(corpWallet);
            organizationService.updateByPrimaryKeySelective(updateOrg);
        } else {
            log.error("创建企业钱包失败");
        }
        List<Integer> sourceList = Arrays.asList(OrganizationSourceEnum.ORGANIZATION_SOURCE_REGISTER.getIndex(),
                OrganizationSourceEnum.ORGANIZATION_SOURCE_WECHATREGISTTER.getIndex(),
                OrganizationSourceEnum.ORGANIZATION_SOURCE_WECHATOFFIREGISTER.getIndex());
        // 创建钱包充值限制配置
        if (StringUtils.isNotBlank(org.getOrgId())) {
            OrgWalletConfigRechargeLimitEnum limit = OrgWalletConfigRechargeLimitEnum.NO_LIMIT;
            if (sourceList.contains(org.getSource())) {
                limit = OrgWalletConfigRechargeLimitEnum.ONLY_ORG_ACCOUNT;
            }
            OrganizationWalletConfigDTO organizationWalletConfigDTO = new OrganizationWalletConfigDTO();
            organizationWalletConfigDTO.setOrgId(org.getOrgId());
            organizationWalletConfigDTO.setRechargeLimit(limit.getType());
            organizationWalletConfigService.insert(organizationWalletConfigDTO);
        }
        //deliverGrpcClientService.getSmsbalanceByOrg(org.getOrgId());
    }

    @Override
    public void orgCreateMessageListener(OrgCreateMessage message) {
        if (log.isInfoEnabled()) {
            log.info("[USER] 用户模块通用队列创建公司消息消费开始. dto: [{}]", JSON.toJSONString(message));
        }
        // 校验参数
        if (message == null || !ObjectId.isValid(message.getOrgId())) {
            if (log.isInfoEnabled()) {
                log.info("[USER] 用户模块通用队列创建公司消息消费失败. msg: [{}] dto: [{}]", "org_id 不能为空", JSON.toJSONString(message));
            }
            return;
        }
        RLock lock = redisService.getLock(userCacheUtil.buildKey(USER_ORG_CREATE_LISTENER_LOCK, message.getOrgId()));
        try {
            boolean res = lock.tryLock(2, 60, TimeUnit.SECONDS);
            if (!res) {
                log.error("[USER] 用户模块通用队列创建公司消息已消费. dto: [{}]", JSON.toJSONString(message));
                return;
            }
            // 创建公司的 mfa setting
            this.createMfaSettingForOrg(message);
            // 创建公司的企业钱包信息
            this.createCorporateWallet(message);

            if (log.isInfoEnabled()) {
                log.info("[USER] 用户模块通用队列创建公司消息消费成功. dto: [{}]", JSON.toJSONString(message));
            }
        } catch (InterruptedException e) {
            log.error("[USER] 用户模块通用队列创建公司消息消费失败. dto: [{}]", JSON.toJSONString(message));
            Thread.currentThread().interrupt();
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}
